﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Timers;
using System.Threading;
using System.Windows.Forms;
using System.Windows.Threading;
using ManagedNite;

using XBMC;

namespace KinectTest1
{
    public partial class Main : Form
    {
        #region Declarations
        SensorHandler hand;
        EventClient eventClient;
        
        System.Timers.Timer intervalTimer;

        int currentX;
        int lastXValue = 3;
        int lastYValue = 8;

        bool dropHandOnDown = false;
        #endregion

        #region Ctor
        public Main()
        {
            InitializeComponent();
            eventClient = new EventClient();
            intervalTimer = new System.Timers.Timer();
        }
        #endregion

        #region FormEvents
        private void Main_Load(object sender, EventArgs e)
        {
            tbIp.Text = Properties.Settings.Default.IpAddress;
        }

        private void butConnect_Click(object sender, EventArgs e)
        {
            Properties.Settings.Default.IpAddress = tbIp.Text;
            Properties.Settings.Default.Save();

            hand = new SensorHandler((int)(7), (int)(7));

            if (!hand.IsOK)
            {
                throw new Exception("Unable to initialize Kinect");
            }

            eventClient.Connect(Properties.Settings.Default.IpAddress);
            eventClient.SendHelo("Kinect Remote v0.01");

            hand.PushDetected += new EventHandler<SelectableSlider2DSelectEventArgs>(hand_PushDetected);
            hand.HoverDetected += new EventHandler<HoverEventArgs>(hand_HoverDetected);

            hand.HandDetectedEvent += new EventHandler<EventArgs>(hand_HandDetectedEvent);
            hand.SessionEnded += new EventHandler<EventArgs>(hand_SessionEnded);

            intervalTimer.Elapsed += new ElapsedEventHandler(intervalTimer_Tick);
        }

        private void intervalTimer_Tick(object sender, ElapsedEventArgs e)
        {
            if (!hand.HandDetected)
                intervalTimer.Stop();

            if (currentX < 3)
            {
                eventClient.SendButton("left", "R1", ButtonFlagsType.BTN_NO_REPEAT);
            }
            else if (currentX == 3)
            {
            }
            else if (currentX > 3)
            {
                eventClient.SendButton("right", "R1", ButtonFlagsType.BTN_NO_REPEAT);
            }
        }
        #endregion

        #region NiteEvents
        void hand_HandDetectedEvent(object sender, EventArgs e)
        {
            dropHandOnDown = false;
            intervalTimer.Start();
            intervalTimer.Interval = 20;

            eventClient.SendNotification("Kinect Remote", "Hand Detected");
        }

        void hand_HoverDetected(object sender, HoverEventArgs e)
        {
            if (dropHandOnDown == true && e.currentY < 2)
            {
                hand.HandDetected = false;
                hand.sessionManager.EndSession();
                intervalTimer.Stop();
                
                eventClient.SendNotification("Kinect Remote", "Stopped tracking");
            }

            if ((e.currentY < lastYValue) && dropHandOnDown)
                return;

            SetText(e.currentX + " - " + e.currentY);
            currentX = e.currentX;

            if (currentX == 0)
            {
                if (lastXValue < currentX)
                    eventClient.SendButton("left", "R1", ButtonFlagsType.BTN_NO_REPEAT);
                intervalTimer.Stop();
                intervalTimer.Interval = 100;
                intervalTimer.Start();
            }
            else if (currentX == 1)
            {
                if (lastXValue < currentX)
                    eventClient.SendButton("left", "R1", ButtonFlagsType.BTN_NO_REPEAT);

                intervalTimer.Stop();
                intervalTimer.Interval = 200;
                intervalTimer.Start();
            }
            else if (currentX == 2)
            {
                if (lastXValue == 3)
                    eventClient.SendButton("left", "R1", ButtonFlagsType.BTN_NO_REPEAT);
                intervalTimer.Interval = 600;
                intervalTimer.Start();
            }
            else if (currentX == 3)
            {
                intervalTimer.Stop();
            }
            else if (currentX == 4)
            {
                if (lastXValue == 3)
                    eventClient.SendButton("right", "R1", ButtonFlagsType.BTN_NO_REPEAT);
                intervalTimer.Interval = 600;
                intervalTimer.Start();
            }
            else if (currentX == 5)
            {
                if (lastXValue < currentX)
                    eventClient.SendButton("right", "R1", ButtonFlagsType.BTN_NO_REPEAT);
                intervalTimer.Stop();
                intervalTimer.Interval = 200;
                intervalTimer.Start();
            }
            else if (currentX == 6)
            {
                if (lastXValue < currentX)
                    eventClient.SendButton("right", "R1", ButtonFlagsType.BTN_NO_REPEAT);

                intervalTimer.Stop();
                intervalTimer.Interval = 100;
                intervalTimer.Start();
            }
            else
            {
                intervalTimer.Interval = 20;
            }
            lastYValue = e.currentY;
            lastXValue = currentX;
        }
        
        void hand_PushDetected(object sender, SelectableSlider2DSelectEventArgs e)
        {
            if (e.SelectDirection == Direction.Forward)
            {
                eventClient.SendNotification("Kinect Remote", "Push Detected");
                eventClient.SendButton("select", "R1", ButtonFlagsType.BTN_NO_REPEAT);
            }
            else
            {
                intervalTimer.Stop();
                eventClient.SendNotification("Kinect Remote", "Hand moved backward, tracking stopped. Move left/right to restart. Down to confirm");
                dropHandOnDown = true;
            }
        }

        void hand_SessionEnded(object sender, EventArgs e)
        {
            eventClient.SendNotification("Kinect Remote", "Hand Lost");
            intervalTimer.Stop();
        }
        #endregion

        #region Delegates
        delegate void SetTextCallback(string text);

        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.textBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.textBox1.Text = text;
            }
        }
        #endregion
    }
}
